
import { eventBus } from '../EventBus';
import { EventListenerOptions } from '../types/EventTypes';

/**
 * 组件事件订阅装饰器
 * 自动在组件生命周期方法中绑定和解绑事件订阅
 * 
 * @param eventName 要订阅的事件名称
 * @param options 订阅选项
 */
export function Subscriber(
  eventName: string,
  options: Omit<EventListenerOptions, 'context'> = {}
) {
  return function (
    target: any,
    methodName: string,
    descriptor: PropertyDescriptor
  ) {
    // 检查目标是否为有效的组件
    if (typeof target.rerender !== 'function') {
      console.warn(`[Subscriber] Decorator can only be used on components with rerender method, target: ${target.constructor.name}`);
      return;
    }

    // 初始化监听器存储
    if (!target.__eventListeners) {
      target.__eventListeners = new Map<string, number>();
    }

    // 保存原始的aboutToAppear方法
    const originalAboutToAppear = target.aboutToAppear;
    
    // 重写aboutToAppear方法
    target.aboutToAppear = function(this: typeof target) {
      // 调用原始方法
      if (typeof originalAboutToAppear === 'function') {
        originalAboutToAppear.call(this);
      }

      // 获取装饰的方法
      const callback = descriptor.value.bind(this);
      
      // 订阅事件，上下文绑定为当前组件实例
      const listenerId = eventBus.on(
        eventName,
        callback,
        { ...options, context: this }
      );
      
      // 存储监听器ID，用于后续取消订阅
      const key = `${eventName}:${methodName}`;
      this.__eventListeners!.set(key, listenerId);
    };

    // 保存原始的aboutToDisappear方法
    const originalAboutToDisappear = target.aboutToDisappear;
    
    // 重写aboutToDisappear方法
    target.aboutToDisappear = function(this: typeof target) {
      // 调用原始方法
      if (typeof originalAboutToDisappear === 'function') {
        originalAboutToDisappear.call(this);
      }

      // 取消订阅
      const key = `${eventName}:${methodName}`;
      const listenerId = this.__eventListeners!.get(key);
      
      if (listenerId !== undefined) {
        eventBus.offById(eventName, listenerId);
        this.__eventListeners!.delete(key);
      }
    };
  };
}

/**
 * 一次性事件订阅装饰器
 * 事件触发一次后自动取消订阅
 * 
 * @param eventName 要订阅的事件名称
 * @param options 订阅选项
 */
export function SubscriberOnce(
  eventName: string,
  options: Omit<EventListenerOptions, 'context' | 'once'> = {}
) {
  return Subscriber(eventName, { ...options, once: true });
}
